package mediadisplay.timeline 
{
	import com.furusystems.logging.slf4as.global.error;
	import com.furusystems.logging.slf4as.global.info;
	import com.furusystems.logging.slf4as.global.warn;
	import com.furusystems.logging.slf4as.ILogger;
	import com.furusystems.logging.slf4as.Logging;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import com.furusystems.dconsole2.DConsole;
	import mediadisplay.MediaArea;
	import mediadisplay.timeline.contenteditarea.ContentEditArea;
	import mediadisplay.timeline.controls.ControlPanel;
	import mediadisplay.timeline.EditArea;
	import mediadisplay.ui.AdminButton;
	import mediadisplay.viewerarea.ScreenText;
	import mediadisplay.viewerarea.ViewerArea;
	
	/**
	 * ...
	 * @author ...
	 */
	public class TimelineContent extends Sprite
	{
		
		public var keypoints:Array;
		public var overviewMarkers:Array;
		public var focusedMarkers:Array;
		private var _trackLength:Number;
		public var soundGraph:SoundGraph;
		public var zoomedTimeline:ZoomedTimeline;
		private var _currentMarker:TimelineOverviewMarker;
		public var _currentFocusedMarker:TimelineFocusedMarker;
		private var movingMarker:Boolean = false;
		public var movingFocusedMarker:Boolean = false;
		public static const L:ILogger = Logging.getLogger(TimelineContent);
		private var resizeSide:String;
		private var mouseDownFirstPosition:Number;
		private var focusedMarkerCurrentLength:Number;
		private var editArea:EditArea;
		public var contentEditArea:ContentEditArea;
		private var controlPanel:ControlPanel;
		private var rowID:int;
		public var loops:Array;
		
		public var mediaArea:MediaArea;
		
		public function TimelineContent(soundGraph:SoundGraph, rowID:int) 
		{
			this.soundGraph = soundGraph;
			this.rowID = rowID;
			
			zoomedTimeline = new ZoomedTimeline(this);
			addChild(zoomedTimeline);
			zoomedTimeline.y = 104;
			
			clear();
			addChild(DConsole.view);
			DConsole.show();
			
			editArea = new EditArea();
			addChild(editArea);
			editArea.y = 155;
			editArea.addEventListener(MouseEvent.MOUSE_DOWN, editAreaMouseDownHandler);
			
			contentEditArea = new ContentEditArea(this);
			addChild(contentEditArea);
			contentEditArea.x = 5;
			contentEditArea.y = -50;
			
			controlPanel = new ControlPanel(soundGraph);
			addChild(controlPanel);
			controlPanel.x = 880;
			controlPanel.y = -35;
			
			mediaArea = new MediaArea(rowID, this);
			addChild(mediaArea);
			
			addEventListener(Event.REMOVED_FROM_STAGE, cleanup);
		}
		
		private function cleanup(e:Event):void 
		{
			removeEventListener(Event.REMOVED_FROM_STAGE, cleanup);
			editArea.removeEventListener(MouseEvent.MOUSE_DOWN, editAreaMouseDownHandler);
			
			for (var i:int = 0; i < overviewMarkers.length; i++) 
			{
				var ovMarker:TimelineOverviewMarker = overviewMarkers[i];
				removeChild(ovMarker);
				
				var fMarker:TimelineFocusedMarker = focusedMarkers[i];
				removeChild(fMarker);
			}
			
			removeChild(zoomedTimeline);
			removeChild(contentEditArea);
			removeChild(controlPanel);
			removeChild(editArea);
			
			clear();
		}
		
		public function setTrackLength(trackLength:Number):void {
			_trackLength = trackLength;
		}
		
		public function changeTextContent(index:int, content:String):void {
			if (keypoints[index] == null) return;
			keypoints[index].content = keypoints[index].focusedMarker.content = overviewMarkers[index].content = content;
			soundGraph._main.viewerArea.objectsOnScreen[index].setText(content);
			focusedMarkers[index].updateText();
		}
		public function clear():void {
			keypoints = new Array;
			loops = new Array;
			overviewMarkers = new Array;
			focusedMarkers = new Array;
		}
		
		/**
		 * Adds a keypoint on the track, takes the time start and stop, content as plain text or URL if image type
		 * @param	start
		 * @param	stop
		 * @param	content
		 * @param	type
		 */
		public function addKeypoint(start:Number, stop:Number, content:String, row:int = 0, type:String = ContentTypes.TEXT_CONTENT, xpos:Number = 0, ypos:Number = 0, zpos:Number = 0, rotationX:Number = 0, rotationY:Number = 0, rotationZ:Number = 0, scale:Number = 1, background:String = "", color:uint = 0xffffff, ignore:Boolean = false, interactionTarget:Number = -1):void {
			if (type == ContentTypes.TEXT_CONTENT) {
				var ob:Object = new Object;
				ob.start = start;
				ob.stop = stop;
				ob.content = content;
				ob.index = keypoints.length;
				ob.type = "text";
				ob.row = row;
				ob.x = xpos;
				ob.y = ypos;
				ob.z = zpos;
				ob.rotationX = rotationX;
				ob.rotationY = rotationY;
				ob.rotationZ = rotationZ;
				ob.background = background;
				ob.scale = scale;
				ob.color = color;
				ob.ignore = ignore;
				ob.interactionTarget = interactionTarget;
				keypoints.push(ob);
				soundGraph._main.viewerArea.addScreenElement(content, ob.index, null, false, xpos, ypos, zpos, rotationX, rotationY, rotationZ, scale, background, color, ignore, interactionTarget);
			} else if (type == ContentTypes.IMAGE_CONTENT) {
				// TODO image content type handling
			} else if (type == ContentTypes.VIDEO_CONTENT) {
				// TODO video content type handling
			}
			drawTimeline();
		}
		
		public function drawTimeline():void {
			cleanupTimeline();
			
			for (var i:int = 0; i < keypoints.length; i++) 
			{
				var keypoint:Object = keypoints[i];
				var timePerPixel:Number = stage.stageWidth / _trackLength * 1000;
				var length:Number = timePerPixel * (Number(keypoint.stop) - Number(keypoint.start));
				var color:uint = keypoint.color;
				var content:String = String(keypoint.content);
				var start:Number = Number(keypoint.start);
				var stop:Number = Number(keypoint.stop);
				var ignore:Boolean = Boolean(keypoint.ignore);
				
				var overviewMarker:TimelineOverviewMarker = new TimelineOverviewMarker(i, length, content, start, stop, color, ignore);
				addChild(overviewMarker);
				overviewMarker.buttonMode = true;
				overviewMarker.addEventListener(MouseEvent.MOUSE_DOWN, overviewMarkerMouseDownHandler);
				
				var size:Number = soundGraph.sliderWindow.width;
				var scale:Number = stage.stageWidth / size;
				
				var focusedMarker:TimelineFocusedMarker = new TimelineFocusedMarker(i, length * scale, content, start, stop, color, ignore);
				addChild(focusedMarker);
				focusedMarker.alpha = 0.9;
				focusedMarker.addEventListener(TimelineFocusedMarker.DELETE_MARKER, deleteMarker);
				focusedMarker.buttonMode = true;
				
				//focusedMarker.mouseChildren = false;	// this makes delete button stop working
				focusedMarker.doubleClickEnabled = true;				
				focusedMarker.addEventListener(MouseEvent.DOUBLE_CLICK, focusedMarkerMouseDoubleClick);
				focusedMarker.addEventListener(MouseEvent.MOUSE_DOWN, focusedMarkerMouseDownHandler);
				
				overviewMarkers.push(overviewMarker);
				focusedMarkers.push(focusedMarker);
				focusedMarker.overviewMarker = overviewMarker;
				overviewMarker.focusedMarker = focusedMarker;
				
				keypoints[i].focusedMarker = focusedMarker;
				keypoints[i].overviewMarker = overviewMarker;
				
				overviewMarker.x = start * timePerPixel;
				overviewMarker.y = 95;
				
				focusedMarker.x = focusedMarker.xPos = (start * timePerPixel) * scale;
				focusedMarker.y = 155;
				
			}
		}
		
		private function focusedMarkerMouseDoubleClick(e:MouseEvent):void 
		{
			var clickedMarker:TimelineFocusedMarker = TimelineFocusedMarker(e.currentTarget);
			var index:int = clickedMarker.index;
			soundGraph._main.viewerArea.moveCamera(index);
		}
		
		private function deleteMarker(e:Event):void 
		{
			var markerIndexToDelete:int = int(e.target.index);
			trace("delete keypoint index " +markerIndexToDelete);
			var focusedMarkerToRemove:TimelineFocusedMarker = TimelineFocusedMarker(e.target);
			var overviewMarkerToRemove:TimelineOverviewMarker = focusedMarkerToRemove.overviewMarker;
			var viewerArea:ViewerArea = soundGraph._main.viewerArea;
			
			// first we remove the overview marker
			removeChild(overviewMarkerToRemove);
			overviewMarkers.splice(markerIndexToDelete, 1);
			// then the focused marker
			removeChild(focusedMarkerToRemove);
			focusedMarkers.splice(markerIndexToDelete, 1);
			// good.  now we can remove the text from the viewer area
			viewerArea.removeScreenElement(markerIndexToDelete);
			// and make sure the edit text area is reset
			contentEditArea.clear();
			// we cant forget to remove the keypoint itself
			keypoints.splice(markerIndexToDelete, 1);
			
			// Now we should be fine!  we need to save the new array!
			soundGraph.saveKeypoints();
		}
		private function editAreaMouseDownHandler(e:MouseEvent):void 
		{
			//var randomColor:uint = Math.random() * 0xffffff;
			var randomColor:uint = 0xffffff;
			
			var timePerPixel:Number = stage.stageWidth / _trackLength * 1000;
			var size:Number = soundGraph.sliderWindow.width;
			var scale:Number = stage.stageWidth / size;
			
			var newStartPosition:Number = (soundGraph.sliderWindow.x / timePerPixel) + (stage.mouseX * (soundGraph.sound.length / stage.stageWidth) / 1000 / scale);	// translate mouseX position to music time
			var newStopPosition:Number = (soundGraph.sliderWindow.x / timePerPixel) + ((stage.mouseX + 20) * (soundGraph.sound.length / stage.stageWidth) / 1000 / scale);
			var len:Number = (newStopPosition - newStartPosition);
			
			var currentScreenX:Number = -soundGraph._main.viewerArea.objectsContainer.x;
			var currentScreenY:Number = -soundGraph._main.viewerArea.objectsContainer.y;
			var currentScreenZ:Number = -soundGraph._main.viewerArea.objectsContainer.z;
			var currentScreenRotationX:Number = -soundGraph._main.viewerArea.objectsContainer.rotationX;
			var currentScreenRotationY:Number = -soundGraph._main.viewerArea.objectsContainer.rotationY;
			var currentScreenRotationZ:Number = -soundGraph._main.viewerArea.objectsContainer.rotationZ;
			
			addKeypoint(newStartPosition, newStopPosition, "[no content]", rowID, ContentTypes.TEXT_CONTENT, currentScreenX, currentScreenY, currentScreenZ, currentScreenRotationX, currentScreenRotationY, currentScreenRotationZ, 1, "", 0xffffff);
			trace("adding keypoint.");
			_currentFocusedMarker = getLastFocusedMarker();
			trace("last marker: " + _currentFocusedMarker);
			_currentFocusedMarker.xPos = (newStartPosition * timePerPixel) * scale;
			focusedMarkerCurrentLength = _currentFocusedMarker.length;
			
			drawTimeline();
			
			contentEditArea.activateAll();
			contentEditArea.edit(keypoints.length - 1);
			contentEditArea.textContent.setText("[no content]");
			var currentIndex:int = _currentFocusedMarker.index;
			var currentElement:ScreenText = soundGraph._main.viewerArea.objectsOnScreen[currentIndex];
			controlPanel.setCurrentElement(currentElement);
		}
		
		private function getLastFocusedMarker():TimelineFocusedMarker {
			return focusedMarkers[focusedMarkers.length - 1];
		}
		
		private function focusedMarkerMouseDownHandler(e:MouseEvent):void 
		{
			if (e.target is AdminButton) return;
			
			movingMarker = true;
			movingFocusedMarker = true;
			mouseDownFirstPosition = stage.mouseX;
			
			_currentFocusedMarker = TimelineFocusedMarker(e.target);
			_currentFocusedMarker.alpha = 1;
			var idx:int = _currentFocusedMarker.index;
			soundGraph.spacecontrol.setObjectToMove(soundGraph._main.viewerArea.objectsOnScreen[idx]);
			soundGraph._main.viewerArea.setActiveObject(soundGraph._main.viewerArea.objectsOnScreen[idx]);
			for (var i:int = 0; i < focusedMarkers.length; i++) 
			{
				var marker:TimelineFocusedMarker = focusedMarkers[i];
				if (marker != _currentFocusedMarker) {
					marker.alpha = 0.9;
				}
			}
			
			focusedMarkerCurrentLength = _currentFocusedMarker.length;
			
			if (_currentFocusedMarker.mouseX < 5) {
				// resize length of focused marker, to the left
				resizeSide = "left";
				stage.addEventListener(MouseEvent.MOUSE_MOVE, resizeFocusedMarkerHandler);	
				stage.addEventListener(MouseEvent.MOUSE_UP, resizeFocusedMarkerMouseUpHandler);
			} else if (_currentFocusedMarker.mouseX > _currentFocusedMarker.width - 8) {
				// resize length of focused marker, to the right
				resizeSide = "right";
				stage.addEventListener(MouseEvent.MOUSE_MOVE, resizeFocusedMarkerHandler);	
				stage.addEventListener(MouseEvent.MOUSE_UP, resizeFocusedMarkerMouseUpHandler);
				
			} else {
				//_currentFocusedMarker = TimelineFocusedMarker(e.target);
				var moveRect:Rectangle = new Rectangle(0, 0, stage.stageWidth, 0);
				moveRect.y = _currentFocusedMarker.y;
				_currentFocusedMarker.startDrag(false, moveRect);
				stage.addEventListener(MouseEvent.MOUSE_MOVE, moveFocusedMarkerHandler);				
				stage.addEventListener(MouseEvent.MOUSE_UP, focusedMarkerMouseUpHandler);
			}
			
			contentEditArea.activateAll();
			contentEditArea.edit(_currentFocusedMarker.index);
			contentEditArea.textContent.setText(_currentFocusedMarker.content);
			contentEditArea.changeTimes(String(_currentFocusedMarker.start), String(_currentFocusedMarker.stop));
			var currentElement:ScreenText = soundGraph._main.viewerArea.objectsOnScreen[idx];
			controlPanel.setCurrentElement(currentElement);
			controlPanel.ignoreBox.setTick(soundGraph._main.viewerArea.objectsOnScreen[idx]._ignore);
		}
		
		private function resizeFocusedMarkerMouseUpHandler(e:MouseEvent):void 
		{
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, resizeFocusedMarkerHandler);	
			stage.removeEventListener(MouseEvent.MOUSE_UP, resizeFocusedMarkerMouseUpHandler);			
		}
		
		private function resizeFocusedMarkerHandler(e:MouseEvent):void 
		{
			var difference:Number;
			var newSize:Number;
			
			if (resizeSide == "right") {
				difference = stage.mouseX - mouseDownFirstPosition;
				newSize = focusedMarkerCurrentLength + difference;
				
				_currentFocusedMarker.length = newSize;
				_currentFocusedMarker.draw(Math.max(5, newSize));
				
				moveFocusedMarkerHandler();
			} else {
				difference = mouseDownFirstPosition - stage.mouseX;
				newSize = Math.max(5, focusedMarkerCurrentLength + difference);
				if (newSize == 5) return;
				_currentFocusedMarker.x = stage.mouseX;
				_currentFocusedMarker.length = newSize;
				_currentFocusedMarker.draw(newSize);
				
				moveFocusedMarkerHandler();
			}
			_currentFocusedMarker.overviewMarker.draw(stage.stageWidth / _trackLength * 1000);
			keypoints[_currentFocusedMarker.index].start = _currentFocusedMarker.start;
			keypoints[_currentFocusedMarker.index].stop = _currentFocusedMarker.stop;
		}
		
		private function moveFocusedMarkerHandler(e:MouseEvent = null):void 
		{
			var timePerPixel:Number = stage.stageWidth / _trackLength * 1000;
			var size:Number = soundGraph.sliderWindow.width;
			var scale:Number = stage.stageWidth / size;
			
			var newStartPosition:Number = (soundGraph.sliderWindow.x / timePerPixel) + (_currentFocusedMarker.x * (soundGraph.sound.length / stage.stageWidth) / 1000 / scale);	// translate mouseX position to music time
			_currentFocusedMarker.xPos = (newStartPosition * timePerPixel) * scale;
			
			var newStopPosition:Number = (soundGraph.sliderWindow.x / timePerPixel) + ((_currentFocusedMarker.x + _currentFocusedMarker.width) * (soundGraph.sound.length / stage.stageWidth) / 1000 / scale);
			var len:Number = (newStopPosition - newStartPosition);
			
			_currentFocusedMarker.overviewMarker.start = _currentFocusedMarker.start = newStartPosition;
			_currentFocusedMarker.overviewMarker.stop = _currentFocusedMarker.stop = newStopPosition;
			_currentFocusedMarker.overviewMarker.x = newStartPosition * timePerPixel;
			
			keypoints[_currentFocusedMarker.index].start = _currentFocusedMarker.overviewMarker.start;
			keypoints[_currentFocusedMarker.index].stop = _currentFocusedMarker.overviewMarker.stop;
			
			contentEditArea.edit(_currentFocusedMarker.index);
			contentEditArea.textContent.setText(_currentFocusedMarker.content);
			contentEditArea.changeTimes(String(newStartPosition), String(newStopPosition));
		}
		
		private function focusedMarkerMouseUpHandler(e:MouseEvent):void 
		{
			if (stage == null) return;
			stage.removeEventListener(MouseEvent.MOUSE_UP, focusedMarkerMouseDownHandler);
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, moveFocusedMarkerHandler);
			_currentFocusedMarker.stopDrag();
			movingMarker = false;
			movingFocusedMarker = false;
		}
		
		private function overviewMarkerMouseDownHandler(e:MouseEvent):void 
		{
			movingMarker = true;
			_currentMarker = TimelineOverviewMarker(e.target);
			var moveRect:Rectangle = new Rectangle(0, 0, stage.stageWidth, 0);
			moveRect.y = _currentMarker.y;
			_currentMarker.startDrag(false, moveRect);
			stage.addEventListener(MouseEvent.MOUSE_UP, overviewMarkerMouseUpHandler);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, moveMarkerHandler);
			
			contentEditArea.activateAll();
			contentEditArea.changeTimes(String(_currentMarker.focusedMarker.start), String(_currentMarker.focusedMarker.stop));
			contentEditArea.edit(_currentMarker.focusedMarker.index);
			contentEditArea.textContent.setText(_currentMarker.focusedMarker.content);
		}
		
		private function moveMarkerHandler(e:MouseEvent):void 
		{
			var timePerPixel:Number = stage.stageWidth / _trackLength * 1000;
			var size:Number = soundGraph.sliderWindow.width;
			var scale:Number = stage.stageWidth / size;
			var newTimePosition:Number = _currentMarker.x * (soundGraph.sound.length / stage.stageWidth) / 1000;	// translate mouseX position to music time
			_currentMarker.focusedMarker.x = _currentMarker.focusedMarker.xPos = (newTimePosition * timePerPixel) * scale;
			
			var len:Number = (_currentMarker.stop - _currentMarker.start);
			_currentMarker.start = newTimePosition;
			_currentMarker.stop = _currentMarker.start + len;
			
			keypoints[_currentMarker.index].start = _currentMarker.start;
			keypoints[_currentMarker.index].stop = _currentMarker.stop;			
			
			contentEditArea.changeTimes(String(_currentMarker.start), String(_currentMarker.stop));
			contentEditArea.edit(_currentMarker.focusedMarker.index);
			contentEditArea.textContent.setText(_currentMarker.focusedMarker.content);
			
			if (!movingFocusedMarker) {
				zoomedTimeline.placeFocusedMarkers();
			}
		}
		
		private function overviewMarkerMouseUpHandler(e:MouseEvent):void 
		{
			stage.removeEventListener(MouseEvent.MOUSE_UP, overviewMarkerMouseUpHandler);
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, moveMarkerHandler);
			_currentMarker.stopDrag();
			movingMarker = false;
		}
		
		private function cleanupTimeline():void 
		{
			for (var i:int = 0; i < overviewMarkers.length; i++) 
			{
				var overviewMarker:TimelineOverviewMarker = overviewMarkers[i];
				removeChild(overviewMarker);
			}
			
			for (var j:int = 0; j < focusedMarkers.length; j++) 
			{
				var focusMarker:TimelineFocusedMarker = focusedMarkers[j];
				removeChild(focusMarker);
			}
			
			overviewMarkers = new Array;
			focusedMarkers = new Array;
		}
		
		public function setWaveformData(data:Array):void {
			zoomedTimeline.drawWaveform(data);
		}
		
		/**
		 * Adds a loop on the track, which will go on forever.  If you want to pass it some time, you will need user interaction!  LOL!!!
		 * @param	triggerpoint
		 * @param	destination
		 */
		public function addLoop(triggerpoint:Number, destination:Number):void 
		{
			var ob:Object = new Object;
			ob.triggerpoint = triggerpoint;
			ob.destination = destination;
			loops.push(ob);			
		}
		
	}

}